package com.dotdashdot.pocketquest;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.TimerTask;

import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.IntentSender.SendIntentException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;

import com.android.vending.billing.IInAppBillingService;
import com.badlogic.gdx.backends.android.AndroidApplication;
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
import com.me.libgdx_test.ActivityMain;

public class MainActivity extends AndroidApplication {
	
	//private ActivityMain activity_holder;
	private AndroidApplicationConfiguration cfg;
	private IInAppBillingService mService;
	private ServiceConnection mServiceConn;
	Bundle buyIntentBundle;
	Object return_object;
	Method return_method;
	private Context self;
	private ClassAndroidLogger logger;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        logger = new ClassAndroidLogger("MainActivity");
        init();
    }

    public void init(){
 	   //super.onResume();
    	
       logger.info("OnInit");
       
       cfg = new AndroidApplicationConfiguration();
       cfg.useGL20 = false;
       
       mService = null;
       return_object = null;
       return_method = null;
       
       self = this;
       
       logger.info("After objects");
    		   
	   mServiceConn = new ServiceConnection() {
		   @Override
		   public void onServiceDisconnected(ComponentName name) {
			   logger.info("Billing Service Disconnected...");
			   mService = null;
		   }

		   @Override
		   public void onServiceConnected(ComponentName name, IBinder service) {
			   logger.info("Billing Service Connected...");
			   mService = IInAppBillingService.Stub.asInterface(service);
		   }
	   };
       
	   logger.info("After service");
	   
	   bindService(new Intent("com.android.vending.billing.InAppBillingService.BIND"), mServiceConn, Context.BIND_AUTO_CREATE);
       
	   logger.info("After bind");
       
       //activity_holder = new ActivityMain();
       initialize(new ActivityMain(new ClassAndroidBillingDirector(mService, this)), cfg);
    }
    
    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mService != null) {
            unbindService(mServiceConn);
        }   
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data)    
    {
        super.onActivityResult(requestCode, resultCode, data);
        logger.info("RequestCode: " + requestCode);
        logger.info("ResultCode: " + resultCode);
        if (requestCode == 1641 && resultCode == Activity.RESULT_OK) {           
        	logger.info("onactivity result called inside request code");
            try{
            	
            	logger.info("Parsing response data");
	            int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
	            logger.info("ResponseCode: " + responseCode);
	            String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
	            logger.info("purchaseData: " + purchaseData);
	            String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
	            logger.info("dataSignature: " + dataSignature);
	            
	            
	            if (responseCode == Constants.BILLING_RESPONSE_RESULT_OK) {
	                try {
	                	if(return_object!=null && return_method!=null){
	                		
	    	                JSONObject jo = new JSONObject(purchaseData);
	    	                String sku = jo.getString("productId");
	    	                logger.info("productId: " + sku);
	    	                //This is where the purchase needs to actually be put into the system...
	    	                
	    	                JSONObject o = new JSONObject(purchaseData);
	    	                logger.info("Purchase Data: " + o.toString());
	    	                String mOrderId = o.optString("orderId");
	    	                logger.info("mOrderId: " + mOrderId);
	    	                String mPackageName = o.optString("packageName");
	    	                logger.info("mPackageName: " + mPackageName);
	    	                String mSku = o.optString("productId");
	    	                logger.info("mSku: " + mSku);
	    	                long mPurchaseTime = o.optLong("purchaseTime");
	    	                logger.info("purchaseTime: " + mPurchaseTime);
	    	                int mPurchaseState = o.optInt("purchaseState");
	    	                logger.info("mPurchaseState: " + mPurchaseState);
	    	                String mDeveloperPayload = o.optString("developerPayload");
	    	                logger.info("mDeveloperPayload: " + mDeveloperPayload);
	    	                String mToken = o.optString("token", o.optString("purchaseToken"));
	    	                logger.info("mToken: " + mToken);
	    	                
	    	                //Need to consume the purchase before returning
	    	                try {
	    	                    mService.consumePurchase(3, getPackageName(), mToken);
	    	                } catch (RemoteException e) {
	    	                	logger.error(e.toString());
	    	                    e.printStackTrace();
	    	                }
	    	                
	    	                //This is the method that reflects back to the prototype
	                		Object[] parameterTypes = new Object[2];
	                        parameterTypes[0] = Integer.valueOf(o.optString("developerPayload").split(">>>")[0]);
	                        parameterTypes[1] = mToken;
	                		
	    					try {
		    	                logger.toast("You have bought the " + sku + ". Excellent choice, adventurer!", self);
	    						return_method.invoke(return_object, parameterTypes);
	    						
	    					} catch (IllegalArgumentException e) {
	    						// TODO Auto-generated catch block
	    						logger.error(e.toString());
	    						e.printStackTrace();
	    					} catch (IllegalAccessException e) {
	    						// TODO Auto-generated catch block
	    						logger.error(e.toString());
	    						e.printStackTrace();
	    					} catch (InvocationTargetException e) {
	    						// TODO Auto-generated catch block
	    						logger.error(e.toString());
	    						e.printStackTrace();
	    					}
	    	                
	                	}
	                }catch (JSONException e) {
	                            Toast.makeText(this, "Failed to parse purchase data.", Toast.LENGTH_SHORT);
	                            logger.error(e.toString());
	                            e.printStackTrace();
	                }
	                }else if (responseCode == Constants.BILLING_RESPONSE_RESULT_USER_CANCELED) {
	                	logger.error("User cancelled purchase"); 
	                	Toast.makeText(this, "User cancelled purchase.", Toast.LENGTH_SHORT).show();
	                }else if (responseCode == Constants.BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE) {
	                	logger.error("Your Device doesn't support inapp billing"); 
	                	Toast.makeText(this, "Your Device doesn't support inapp billing.", Toast.LENGTH_SHORT).show();
	                }else if (responseCode == Constants.BILLING_RESPONSE_RESULT_ITEM_UNAVAILABLE) {
	                	logger.error("Item is not available for billing"); 
	                	Toast.makeText(this, "Item is not available for billing", Toast.LENGTH_SHORT).show();
	                }else if (responseCode == Constants.BILLING_RESPONSE_RESULT_DEVELOPER_ERROR) {
	                	logger.error("Can't purchase item due to some developer error"); 
	                	Toast.makeText(this, "Can't purchase item due to some developer error.", Toast.LENGTH_SHORT).show();
	                }else if (responseCode == Constants.BILLING_RESPONSE_RESULT_ERROR) {
	                	logger.error("Can't purchase item due to some error in response"); 
	                	Toast.makeText(this, "Can't purchase item due to some error in response.", Toast.LENGTH_SHORT).show();
	                }else if (responseCode == Constants.BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED) {
	                	logger.error("You already own this item"); 
	                	Toast.makeText(this, "You already own this item.", Toast.LENGTH_SHORT).show();
	                }else if (responseCode == Constants.BILLING_RESPONSE_RESULT_ITEM_NOT_OWNED) {
	                	logger.error("You don't own this item");
	                    Toast.makeText(this, "You don't own this item.", Toast.LENGTH_SHORT).show();
	                }
            }catch(Exception e){
            	logger.error(e.toString());
            	logger.error("Unable to make purchase");
            	Toast.makeText(this, "Unable to make purchase.", Toast.LENGTH_SHORT).show();
            }
        }
        
    }
    
    public class Constants{
    	static final int BILLING_RESPONSE_RESULT_OK	= 0;
    	static final int BILLING_RESPONSE_RESULT_USER_CANCELED = 1;
    	static final int BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE = 3;
    	static final int BILLING_RESPONSE_RESULT_ITEM_UNAVAILABLE	= 4;
    	static final int BILLING_RESPONSE_RESULT_DEVELOPER_ERROR = 5;
    	static final int BILLING_RESPONSE_RESULT_ERROR = 6;
    	static final int BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED = 7;
    	static final int BILLING_RESPONSE_RESULT_ITEM_NOT_OWNED = 8;
    }
    
    public void call_billing_task(IInAppBillingService mService, String payload, String item_name){
    	
    	logger.info("call billing task");
    	
    	LoadBillingTask task = new LoadBillingTask(payload, item_name);
    	
    	task.run();
    	
    	/*load_billing_task task = new load_billing_task(mService, payload, item_name);
    	task.execute();*/
    }
    
    class LoadBillingTask extends TimerTask {
        private Handler mHandler = new Handler(Looper.getMainLooper());
		String payload;
		String item_name;

        LoadBillingTask(String payload, String item_name){
        	logger.info("Init Billing");
  			this.payload = payload;
  			this.item_name = item_name;
  			logger.info("Done Init Billing");
        }
        
        @Override
        public void run() {
           mHandler.post(new Runnable() {
              public void run() {
            	  try {
            		  logger.info("Starting runnable");
            		  logger.info("package: " + getPackageName());
            		  logger.info("item: " + item_name);
            		  logger.info("payload: " + payload);
            		if(mService == null){
            			logger.info("mService: invalid");
            			Toast.makeText(self, "There was a problem connecting to the billing service", 1000);
            		}else{
            			logger.info("mService: valid");
            			buyIntentBundle = mService.getBuyIntent(3, getPackageName(), item_name, "inapp", payload);
            			logger.info("Intent info");
            			/*logger.info("Response: " + buyIntentBundle.getParcelable("RESPONSE_CODE").toString());
            			logger.info("Buy Intent: " + buyIntentBundle.getParcelable("BUY_INTENT").toString());
            			logger.info("Purchase Data: " + buyIntentBundle.getParcelable("INAPP_PURCHASE_DATA").toString());
            			logger.info("Data Signature: " + buyIntentBundle.getParcelable("INAPP_DATA_SIGNATURE").toString());*/
            			//If the response code is 7, we need to consume the purchase and try again...
            			/*if(buyIntentBundle.getInt("RESPONSE_CODE") == 7){
            				//INAPP_PURCHASE_DATA_LIST 
            				logger.info("Product already purchased");
            				
            			   ArrayList<String> ownedSkus =
            					   buyIntentBundle.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
    					   ArrayList<String>  purchaseDataList =
    							   buyIntentBundle.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
    					   ArrayList<String>  signatureList =
    							   buyIntentBundle.getStringArrayList("INAPP_DATA_SIGNATURE");
    					   String continuationToken = 
    							   buyIntentBundle.getString("INAPP_CONTINUATION_TOKEN");
	        				logger.info("Printing Purchase Data...");
	        				logger.info("continuationToken: " + continuationToken);
	        				for (int i = 0; i < purchaseDataList.size(); ++i) {
	        					logger.info(purchaseDataList.get(i));
	        					logger.info(signatureList.get(i));
	        					logger.info(ownedSkus.get(i));
	        				   } */
            			if(buyIntentBundle.getInt("RESPONSE_CODE") != 7){
	            			logger.info("Starting pending intent");
	            			
	          				PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
	          				
	          				logger.info("Starting sender for result");
	          				startIntentSenderForResult(pendingIntent.getIntentSender(),
	          					   1641, new Intent(), Integer.valueOf(0), Integer.valueOf(0),
	          					   Integer.valueOf(0));
            			}else{
            				logger.toast("This product has already been purchased!", self);
            			}
            		}
      			} catch (RemoteException e) {
      				logger.error(e.toString());
      				e.printStackTrace();
      			} catch (SendIntentException e) {
      				logger.error(e.toString());
      				e.printStackTrace();
      			} catch (Exception e){
      				logger.error(e.toString());
      				e.printStackTrace();
      			}
              }
           });
         }
    }
    
    /*public class load_billing_task extends AsyncTask<Void, Void, Void> {
		IInAppBillingService  mService;
		String payload;
		String item_name;

		load_billing_task(IInAppBillingService mService, String payload, String item_name){
  			this.mService = mService;
  			this.payload = payload;
  			this.item_name = item_name;
  		}
  		
  		@Override
        protected void onPreExecute() {}
  		
  		@Override
  		protected Void doInBackground(Void... arg0) {
			try {
				buyIntentBundle = mService.getBuyIntent(3, getPackageName(),item_name, "inapp", payload);
	  			PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
				startIntentSenderForResult(pendingIntent.getIntentSender(),
					   1641, new Intent(), Integer.valueOf(0), Integer.valueOf(0),
					   Integer.valueOf(0));
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (SendIntentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
  			return null;
  		}
  		
  		@Override
  	    protected void onPostExecute(Void v) {}
  		
  	}*/
}